﻿/// CSS 2.1
///
[<AutoOpen>]
module WingBeats.CSS.Beats

open WingBeats.CSS.AST
open Common

let stylesheet variables domains =
    Stylesheet (variables, domains)

let domain selector declarations subRules =
    Domain (selector, declarations, subRules)

let rule selector declarations =
    domain selector declarations []

let declaration name value =
    Declaration (name, StringValue (value, None))

// Box
let margin = declaration "margin"
[<RequireQualifiedAccess>]
module Margin =
    let top    = declaration "margin-top"
    let right  = declaration "margin-right" 
    let bottom = declaration "margin-bottom"
    let left   = declaration "margin-left"
    let all top right bottom left =
        declaration "margin" ((sprintf "%s %s %s %s" top right bottom left).Trim())

let padding = declaration "padding"
[<RequireQualifiedAccess>]
module Padding =
    let top    = declaration "padding-top"    
    let right  = declaration "padding-right"  
    let bottom = declaration "padding-bottom" 
    let left   = declaration "padding-left"   
    let all top right bottom left =
        declaration "padding" ((sprintf "%s %s %s %s" top right bottom left).Trim())

let border (values : BorderValues) = 
    declaration "border" (sprintf "%s %s %s" values.Style values.Width values.Color)
[<RequireQualifiedAccess>]
module Border =

    let width = declaration "border-width"
    module Width =
        let all top right bottom left = 
            declaration "border-width" ((sprintf "%s %s %s %s" top right bottom left).Trim())

    let color = declaration "border-color"
    module Color =
        let all top right bottom left = 
            declaration "border-color" ((sprintf "%s %s %s %s" top right bottom left).Trim())
    
    let style = declaration "border-style"
    [<RequireQualifiedAccess>]
    module Style =
        let inherit_ = declaration "border-style" inherit_
        let none     = declaration "border-style" none
        let hidden = declaration "border-style" "hidden"
        let dotted = declaration "border-style" "dotted"
        let dashed = declaration "border-style" "dashed"
        let solid  = declaration "border-style" "solid"
        let double = declaration "border-style" "double"
        let groove = declaration "border-style" "groove"
        let ridge  = declaration "border-style" "ridge"
        let inset  = declaration "border-style" "inset"
        let outset = declaration "border-style" "outset"  
        let all top right bottom left = 
            declaration "border-style" ((sprintf "%s %s %s %s" top right bottom left).Trim())

    let top style width color = 
        declaration "border-top" (sprintf "%s %s %s" style width color)
    
    [<RequireQualifiedAccess>]
    module Top =
        let width = declaration "border-top-width" 
        let color = declaration "border-top-color" 
        [<RequireQualifiedAccess>]
        module Style =
            let inherit_ = declaration "border-top-style" inherit_
            let none     = declaration "border-top-style" none
            let hidden = declaration "border-top-style" "hidden"
            let dotted = declaration "border-top-style" "dotted"
            let dashed = declaration "border-top-style" "dashed"
            let solid  = declaration "border-top-style" "solid"
            let double = declaration "border-top-style" "double"
            let groove = declaration "border-top-style" "groove"
            let ridge  = declaration "border-top-style" "ridge"
            let inset  = declaration "border-top-style" "inset"
            let outset = declaration "border-top-style" "outset" 

    let right style width color =
        declaration "border-right" (sprintf "%s %s %s" style width color)
    [<RequireQualifiedAccess>]
    module Right =
        let width = declaration "border-right-width" 
        let color = declaration "border-right-color" 
        [<RequireQualifiedAccess>]
        module Style =
            let inherit_ = declaration "border-right-style" inherit_
            let none     = declaration "border-right-style" none
            let hidden = declaration "border-right-style" "hidden"
            let dotted = declaration "border-right-style" "dotted"
            let dashed = declaration "border-right-style" "dashed"
            let solid  = declaration "border-right-style" "solid"
            let double = declaration "border-right-style" "double"
            let groove = declaration "border-right-style" "groove"
            let ridge  = declaration "border-right-style" "ridge"
            let inset  = declaration "border-right-style" "inset"
            let outset = declaration "border-right-style" "outset" 

    let bottom style width color =
        declaration "border-bottom" (sprintf "%s %s %s" style width color)
    [<RequireQualifiedAccess>]
    module Bottom =
        let width = declaration "border-bottom-width" 
        let color = declaration "border-bottom-color" 
        let style = declaration "border-bottom-style" 
        [<RequireQualifiedAccess>]
        module Style =
            let inherit_ = declaration "border-bottom-style" inherit_
            let none     = declaration "border-bottom-style" none
            let hidden = declaration "border-bottom-style" "hidden"
            let dotted = declaration "border-bottom-style" "dotted"
            let dashed = declaration "border-bottom-style" "dashed"
            let solid  = declaration "border-bottom-style" "solid"
            let double = declaration "border-bottom-style" "double"
            let groove = declaration "border-bottom-style" "groove"
            let ridge  = declaration "border-bottom-style" "ridge"
            let inset  = declaration "border-bottom-style" "inset"
            let outset = declaration "border-bottom-style" "outset" 
    
    let left style width color =
        declaration "border-left" (sprintf "%s %s %s" style width color)
    [<RequireQualifiedAccess>]
    module Left =
        let width = declaration "border-left-width" 
        let color = declaration "border-left-color" 
        [<RequireQualifiedAccess>]
        module Style =
            let inherit_ = declaration "border-left-style" inherit_
            let none     = declaration "border-left-style" none
            let hidden = declaration "border-left-style" "hidden"
            let dotted = declaration "border-left-style" "dotted"
            let dashed = declaration "border-left-style" "dashed"
            let solid  = declaration "border-left-style" "solid"
            let double = declaration "border-left-style" "double"
            let groove = declaration "border-left-style" "groove"
            let ridge  = declaration "border-left-style" "ridge"
            let inset  = declaration "border-left-style" "inset"
            let outset = declaration "border-left-style" "outset" 
    
    [<RequireQualifiedAccess>]
    module Collapse =
        let private collapse_ = declaration "border-collapse"
        let collapse = collapse_ "collapse"
        let separate = collapse_ "separate"
        let inherit_ = collapse_ inherit_

    let spacing (x : string) y = declaration "border-spacing" ((x + " " + y).Trim())
    [<RequireQualifiedAccess>]
    module Spacing =
        let inherit_ = spacing inherit_ ""


// Layout
[<RequireQualifiedAccess>]
module Float =
    let private float = declaration "float"
    let left     = float Align.left
    let right    = float Align.right
    let none     = float none
    let inherit_ = float inherit_
[<RequireQualifiedAccess>]
module Clear =
    let private clear = declaration "clear"
    let left     = clear Align.left
    let right    = clear Align.right
    let both     = clear "both"
    let none     = clear none
    let inherit_ = clear inherit_
[<RequireQualifiedAccess>]
module Display =
    let private display = declaration "display"
    let block       = display "block"
    let inlineBlock = display "inline-block"
    let inline_     = display "inline"
    let listItem    = display "list-item"
    let none        = display none
    let runIn       = display "run-in"
    let table       = display "table"
    let inherit_    = display inherit_
    module Table =
        let inline_     = display "table-inline"
        let rowGroup    = display "table-row-group"
        let column      = display "table-column"
        let columnGroup = display "table-column-group"
        let headerGroup = display "table-header-group"
        let footerGroup = display "table-footer-group"
        let row         = display "table-row"
        let cell        = display "table-cell"
        let caption     = display "table-caption"
[<RequireQualifiedAccess>]
module Position =
    let private position = declaration "position"
    let static_  = position "static"
    let relative = position "relative"
    let absolute = position "absolute"
    let fixed_   = position "fixed"
    let inherit_ = position inherit_

let top    = declaration "top"    
let right  = declaration "right"  
let bottom = declaration "bottom" 
let left   = declaration "left"   

let zIndex (i : int) = declaration "z-index" (i.ToString())
[<RequireQualifiedAccess>]
module ZIndex =
    let auto     = declaration "z-index" auto
    let inherit_ = declaration "z-index" inherit_

[<RequireQualifiedAccess>]
module Direction =
    let private zIndex = declaration "z-index"
    let inherit_ = zIndex inherit_
    /// Left-to-right direction
    let ltr      = zIndex "ltr"
    /// Right-to-left direction
    let rtl      = zIndex "rtl"

// Typography
let fontSize = declaration "font-size"

// Backgrounds and colors
let color = declaration "color"

let background (values : BackgroundValues) = 
    let x, y = values.Position
    declaration 
        "background" 
        ((sprintf 
            "%s %s %s %s %s %s"
            values.Color
            values.Image
            values.Repeat
            values.Attachment
            x
            y).Trim())       

[<RequireQualifiedAccess>]
module Background =
    let color    = declaration "background-color"
    let image    = declaration "background-image"
    let position (x : string) (y : string) = 
        declaration "background-position" ((x + " " + y).Trim())
    [<RequireQualifiedAccess>]
    module Repeat =
        let private repeat_ = declaration "background-repeat"
        let repeat   = repeat_ "repeat"
        let repeatX  = repeat_ "repeat-x"
        let repeatY  = repeat_ "repeat-y"
        let noRepeat = repeat_ "no-reepat"
        let inherit_ = repeat_ inherit_
    [<RequireQualifiedAccess>]
    module Attachment =
        let private attachment = declaration "background-attachment"
        let scroll   = attachment "scroll"
        let fixed_   = attachment "fixed"
        let inherit_ = attachment inherit_


// Visual formatting
let height    = declaration "height"
let minHeight = declaration "min-height"
let maxHeight = declaration "max-height"
let width     = declaration "width" 
let minWidth  = declaration "min-width"
let maxWidth  = declaration "max-width"

let lineHeight = declaration "line-height"
[<RequireQualifiedAccess>]
module LineHeight =
    let normal = lineHeight normal

let verticalAlign = declaration "vertical-align"
[<RequireQualifiedAccess>]
module VerticalAlign =
    let baseLine   = verticalAlign "baseLine"
    let sub        = verticalAlign "sub"
    let super      = verticalAlign "super"
    let top        = verticalAlign "top"
    let textTop    = verticalAlign "text-top"
    let middle     = verticalAlign "middle"
    let bottom     = verticalAlign "bottom"
    let textBottom = verticalAlign "text-bottom"

// Visual effects
[<RequireQualifiedAccess>]
module Overflow =
    let private overflow = declaration "overflow"
    let visible  = overflow "visible"
    let hidden   = overflow "hidden"
    let scroll   = overflow "scroll"
    let auto     = overflow "auto"
    let inherit_ = overflow "inherit"

[<RequireQualifiedAccess>]
module Clip =
    let private clip = declaration "clip"
    let auto     = clip auto
    let inherit_ = clip inherit_
    let rect (top, right, bottom, left) = 
        clip (sprintf "rect(%s,%s,%s,%s)" top right bottom left)

[<RequireQualifiedAccess>]
module Visibility =
    let private visibility = declaration "visibility"
    let visible  = visibility "visible"
    let hidden   = visibility "hidden"
    let collapse = visibility "collapse"
    let inherit_ = visibility inherit_

// Generated content
let content = declaration "content"
let quotes  = declaration "quote"

[<RequireQualifiedAccess>]
module Counter =
    let reset = declaration "counter-reset"
    [<RequireQualifiedAccess>]
    module Reset =
        let none     = reset none
        let inherit_ = reset inherit_
    let increment = declaration "counter-increment"
    [<RequireQualifiedAccess>]
    module Increment =
        let none     = increment none
        let inherit_ = increment inherit_

// Lists
let listStyle (values : ListStyleValues) = 
    declaration "list-style" 
        ((sprintf 
            "%s %s %s %s" 
            values.Type 
            (fst values.Position)
            (snd values.Position)
             values.Image).Trim())

[<RequireQualifiedAccess>]
module ListStyle =
    [<RequireQualifiedAccess>]
    module Type =
        let private type_ = declaration "list-style-type"
        let disc     = type_ "disc"
        let circle   = type_ "circle"
        let square   = type_ "square"
        let decimal  = type_ "decimal"
        let decimalLeadingZero = type_ "decimal-leading-zero"
        let lowerRoman = type_ "lower-roman"
        let upperRoman = type_ "upper-roman"
        let lowerGreek = type_ "lower-greek"
        let lowerLatin = type_ "lower-latin"
        let upperLatin = type_ "upper-latin"
        let armenian   = type_ "armenian"
        let georgian   = type_ "georgian"
        let lowerAlpha = type_ "lower-alpha"
        let upperAlpha = type_ "upper-alpha"
        let none       = type_ none
        let inherit_   = type_ inherit_

    let image = declaration "list-style-image"

    [<RequireQualifiedAccess>]
    module Position =
        let private position = declaration "list-style-positin"
        let inside   = position "inside"
        let outside  = position "outside"
        let inherit_ = position "inherit"

// Page
[<RequireQualifiedAccess>]
module PageBreak =
    [<RequireQualifiedAccess>]
    module Before =
        let private before = declaration "page-break-before"
        let auto     = before auto
        let always   = before "always"
        let avoid    = before "avoid"
        let left     = before "left"
        let right    = before "right"
        let inherit_ = before inherit_ 
    
    [<RequireQualifiedAccess>]
    module After =
        let private after = declaration "page-break-after"
        let auto     = after auto
        let always   = after "always"
        let avoid    = after "avoid"
        let left     = after "left"
        let right    = after "right"
        let inherit_ = after inherit_ 

    [<RequireQualifiedAccess>]
    module Inside =
        let private inside = declaration "page-break-inside"
        let auto     = inside auto
        let avoid    = inside "avoid"
        let inherit_ = inside inherit_

let orphans (i : int) = declaration "orphans" (i.ToString())
[<RequireQualifiedAccess>]
module Orphans =
    let inherit_ = declaration "orphans" inherit_

let widows (i : int) = declaration "widows" (i.ToString())
[<RequireQualifiedAccess>]
module Widows =
    let inherit_ = declaration "widows" inherit_

// Fonts
let font (values : FontValues) = 
    declaration 
        "font"
        ((sprintf 
            "%s %s %s %s %s %s"
            values.Style
            values.Variant
            values.Weight
            values.Size
            values.LineHeight
            values.FontFamily).Trim().Replace("  ", ""))
[<RequireQualifiedAccess>]
module Font =
    let family (value : string seq) = 
        declaration 
            "font-family" 
            (value |> foldStrings ",")
    let size = declaration "font-size"
    [<RequireQualifiedAccess>]
    module Style =
        let private style = declaration "font-style"
        let normal   = style normal
        let italic   = style "italic"
        let oblique  = style "oblique"
        let inherit_ = style inherit_
    [<RequireQualifiedAccess>]
    module Variant =
        let private variant = declaration "font-variant"
        let normal    = variant normal
        let smallCaps = variant "small-caps"
        let inherit_  = variant inherit_
    [<RequireQualifiedAccess>]
    module Weight =
        let private weight = declaration "font-weight"
        let normal   = weight normal
        let bold     = weight "bold"
        let bolder   = weight "bolder"
        let lighter  = weight "lighter"
        let _100     = weight "100"
        let _200     = weight "200"
        let _300     = weight "300"
        let _400     = weight "400"
        let _500     = weight "500"
        let _600     = weight "600"
        let _700     = weight "700"
        let _800     = weight "800"
        let _900     = weight "900"
        let inherit_ = weight inherit_
    [<RequireQualifiedAccess>]
    module System =
        let private font systemFont (values : SystemFontValues) =
            declaration "font"
                ((sprintf 
                    "%s %s %s %s %s"
                    values.Style
                    values.Variant
                    values.Weight
                    values.Size
                    systemFont).Trim().Replace("  ", ""))
        let caption      = font "caption"
        let icon         = font "icon"
        let menu         = font "menu"
        let messageBox   = font "message-box"
        let smallCaption = font "small-caption"
        let statusBar    = font "status-bar"

// Text
[<RequireQualifiedAccess>]
module Text =
    let indent = declaration "text-indent"
    let decoration (value : string seq) = 
        declaration 
            "text-decoration"
            (value |> foldStrings " ")
    [<RequireQualifiedAccess>]
    module Decoration =
        let none     = decoration [none]
        let inherit_ = decoration [inherit_]
    [<RequireQualifiedAccess>]
    module Align =
        let private align = declaration "text-align"
        let left     = align Align.left
        let right    = align Align.right
        let center   = align Align.center
        let justify  = align "justify"
        let inherit_ = align inherit_
    [<RequireQualifiedAccess>]
    module Transform =
        let private transform = declaration "transform"
        let capitalize = transform "capitalize"
        let uppercase  = transform "uppercase"
        let lowercase  = transform "lowercase"
        let none       = transform none
        let inherit_   = transform inherit_

let letterSpacing = declaration "letter-spacing"
let wordSpacing   = declaration "word-spacing"
[<RequireQualifiedAccess>]
module WhiteSpacing = 
    let private whiteSpacing = declaration "white-spacing"
    let normal   = whiteSpacing normal
    let pre      = whiteSpacing "pre"
    let nowrap   = whiteSpacing "nowrap"
    let preWrap  = whiteSpacing "pre-wrap"
    let preLine  = whiteSpacing "pre-line"
    let inherit_ = whiteSpacing inherit_
     
// Tables
[<RequireQualifiedAccess>]
module CaptionSide = 
    let private captionSide = declaration "caption-side"
    let top      = captionSide Align.top
    let bottom   = captionSide Align.bottom
    let inherit_ = captionSide inherit_
 
[<RequireQualifiedAccess>]
module TableLayout =    
    let private tableLayout = declaration "table-layout"
    let auto     = tableLayout auto
    let fixed_   = tableLayout "fixed"
    let inherit_ = tableLayout inherit_

[<RequireQualifiedAccess>]
module EmptyCells = 
    let private emptyCells = declaration "empty-cells"
    let show     = emptyCells "show"
    let hide     = emptyCells "hide"
    let inherit_ = emptyCells inherit_

// User interface
[<RequireQualifiedAccess>]
module Cursor = 
    let private cursor cursorType (uris : string seq) = 
        declaration 
            "cursor"
            ( (uris |> foldStrings ",") + cursorType )

    let auto      uris = cursor auto        uris
    let crosshair uris = cursor "crosshair" uris
    let default_  uris = cursor "default"   uris
    let pointer   uris = cursor "pointer"   uris
    let move      uris = cursor "move"      uris
    let eResize   uris = cursor "e-resize"  uris
    let neResize  uris = cursor "ne-resize" uris
    let nwResize  uris = cursor "nw-resize" uris
    let nResize   uris = cursor "n-resize"  uris
    let seResize  uris = cursor "se-resize" uris
    let swResize  uris = cursor "sw-resize" uris
    let sResize   uris = cursor "s-resize"  uris
    let wResize   uris = cursor "w-resize"  uris
    let text      uris = cursor "text"      uris
    let wait      uris = cursor "wait"      uris
    let help      uris = cursor "help"      uris
    let progress  uris = cursor "progress"  uris
    let inherit_  uris = cursor inherit_    uris

let outline (values : BorderValues) =
    declaration 
        "outline"
        ((sprintf 
            "%s %s %s"
            values.Color
            values.Style
            values.Width).Trim().Replace("  ", ""))
[<RequireQualifiedAccess>]
module Outline =  
    let inherit_ = declaration "outline" inherit_       
    let width    = declaration "outline-width"
    let style    = declaration "outline-style"
    let color    = declaration "outline-color"

